package com.systemframework.pay.service.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConstants;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.systemframework.exception.ResultException;
import com.systemframework.pay.config.AliPayProperties;
import com.systemframework.pay.model.PayOrderRequestDTO;
import com.systemframework.pay.service.PayCommon;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @author summer
 * @date 2023-11-01 9:49
 */
@Service
@AllArgsConstructor
@Slf4j
public class AlPay implements PayCommon {

    private final AlipayClient alipayClient;


    @Override
    public String nativePay(PayOrderRequestDTO payOrderRequestDTO, HttpServletRequest request) {
        AlipayTradePrecreateModel alipayTradePrecreateModel = alipayTradePrecreateModel(payOrderRequestDTO);
        AlipayTradePrecreateRequest alipayTradePrecreateRequest = new AlipayTradePrecreateRequest();
        alipayTradePrecreateRequest.setBizModel(alipayTradePrecreateModel);
        alipayTradePrecreateRequest.setNotifyUrl(payOrderRequestDTO.getNotifyUrl());
        try {
            AlipayTradePrecreateResponse alipayTradePrecreateResponse = alipayClient.execute(alipayTradePrecreateRequest);
            String resultStr = alipayTradePrecreateResponse.getBody();
            JSONObject jsonObject = JSONObject.parseObject(resultStr);
            String code = jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code");
            return QrCodeUtil.generateAsBase64(code, new QrConfig(200, 200), "png");
        }catch (Exception e){
            log.error("error:", e.getMessage(),e);
            throw new ResultException("支付宝二维码支付失败");
        }
    }

    @Override
    public Map<String, Object> appPay(PayOrderRequestDTO payOrderRequestDTO) {
        AlipayTradePrecreateModel alipayTradePrecreateModel = alipayTradePrecreateModel(payOrderRequestDTO);
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        request.setBizModel(alipayTradePrecreateModel);
        request.setNotifyUrl(payOrderRequestDTO.getNotifyUrl());
        try {
            AlipayTradeAppPayResponse alipayTradeAppPayResponse = alipayClient.sdkExecute(request);
            String object = JSON.parseObject(alipayTradeAppPayResponse.getBody()).getString("alipay_trade_app_pay_response");
            return JSON.parseObject(object,new TypeReference<Map<String,Object>>(){});
        }catch (Exception e){
            throw new ResultException("支付宝APP支付失败");
        }
    }

    @Override
    public String h5Pay(PayOrderRequestDTO payOrderRequestDTO, HttpServletRequest request) {
        AlipayTradePrecreateModel alipayTradePrecreateModel = alipayTradePrecreateModel(payOrderRequestDTO);
        AlipayTradeWapPayRequest wapPayRequest = new  AlipayTradeWapPayRequest();
        wapPayRequest.setBizModel(alipayTradePrecreateModel);
        wapPayRequest.setNotifyUrl(payOrderRequestDTO.getNotifyUrl());
        try {
            AlipayTradeWapPayResponse alipayTradeWapPayResponse = alipayClient.pageExecute(wapPayRequest);
            return alipayTradeWapPayResponse.getBody();
        }catch (Exception e){
            throw new ResultException("支付宝h5支付失败");
        }
    }

    private AlipayTradePrecreateModel alipayTradePrecreateModel(PayOrderRequestDTO payOrderRequestDTO){
        AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
        model.setSubject(payOrderRequestDTO.getProductName());
        model.setTotalAmount(payOrderRequestDTO.getProductPrice());
        model.setOutTradeNo(payOrderRequestDTO.getOrderNo());
        return model;
    }

    private AliPayProperties aliPayProperties;

    @Autowired
    public void setAliPayProperties(AliPayProperties aliPayProperties) {
        this.aliPayProperties = aliPayProperties;
    }

    public Map<String,Object> notifyResult(HttpServletRequest request){
        try {
            HashMap<String, Object> objectHashMap = MapUtil.newHashMap();
            request.setCharacterEncoding("utf-8");
            Map<String, String> params =  getMap(request.getParameterMap());
            log.info("params:{}",params);
            String outTradeNo = new String(params.get("out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
            String tradeNo = new String(params.get("trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

            boolean signVerified = AlipaySignature.rsaCheckV1(params, aliPayProperties.getAlipayPublicKey(), AlipayConstants.CHARSET_UTF8,AlipayConstants.SIGN_TYPE_RSA2);
            log.info("signVerified:{}",signVerified);
            objectHashMap.put("orderNo",outTradeNo);
            objectHashMap.put("sign",signVerified);
            return objectHashMap;
        }catch (Exception e){
            log.error("支付宝回调失败:{}",e.getMessage(),e);
            throw new ResultException("支付宝支付失败");
        }

    }


    private   Map<String,String> getMap(Map<String, String[]> requestParams){
        Map<String, String> params = new HashMap<>(8);
        for (Map.Entry<String, String[]> stringEntry : requestParams.entrySet()) {
            String[] values = stringEntry.getValue();
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            params.put(stringEntry.getKey(), valueStr);
        }
        return params;
    }
}
